/*
 * @(#)JaroWinklerFunction.java
 *
 * Revision:
 * Author                                         Date           
 * --------------------------------------------   ------------   
 * Ana Emilia Victor Barbosa Coutinho             25/09/2013    
 */
package br.edu.ufcg.splab.techniques.reduction.functions.similarity;

import br.edu.ufcg.splab.generator.TestCase;

public class JaroWinklerFunction extends JaroFunction implements DistanceFunction{
	final double DEFAULT_SCALING_FACTOR = 0.1;  // This is the default scaling factor Winkler used.

	private double scalingFactor;

	/**
	 * Constructs a new JaroWinklerStrategy instance.
	 */
	public JaroWinklerFunction()	{
		this.scalingFactor = DEFAULT_SCALING_FACTOR;
	}

	/**
     * Provide a string representation of the similarity function to be written.
     * @return The string representation of the similarity function.
     */
	public String getFunctionName(){
		return "JW";
	}
	
	/**
	 * Calculates the similarity score of objects, where 0.0 implies absolutely no similarity
	 * and 1.0 implies absolute similarity.
	 *
	 * @param first The first string to compare.
	 * @param second The second string to compare.
	 * @return A number between 0.0 and 1.0.
	 */
	public double getSimilarity(TestCase first, TestCase second)
	{
		double jaro = super.getSimilarity(first, second);

		int cl = commonPrefixLength(first, second);

		System.out.println("jaro www: " + jaro);
		// The Jaro-Winkler distance uses a prefix scale which gives more favorable ratings
		// to strings that match from the beginning for a set prefix length.
		double winkler = jaro + (scalingFactor * cl * (1.0 - jaro));
		return winkler;

	}

	/**
	 * Calculates the number of characters from the beginning of the strings that match exactly one-to-one,
	 * up to a maximum of four (4) characters.
	 * @param first The first string.
	 * @param second The second string.
	 * @return A number between 0 and 4.
	 */
	private int commonPrefixLength(TestCase first, TestCase second)	{
		TestCase shorter;
		TestCase longer;

		// Determine which string is longer.
		if (first.getTestCase().size() > second.getTestCase().size())		{
			longer = first;
			shorter = second;
		}else{
			longer = second;
			shorter = first;
		}

		int result = 0;

		// Iterate through the shorter string.
		for (int i = 0; i < shorter.getTestCase().size(); i++){
			if (shorter.getTestCase().get(i) != longer.getTestCase().get(i)){
				break;
			}
			result++;
		}

		// Limit the result to 4.
		return result > 4? 4: result;
	}
	
}
